using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Microsoft.Practices.Repository
{
    /// <summary>
    /// This interface specifies the signature for a factory that
    /// takes a DataReader and creates a domain object from it.
    /// </summary>
    /// <remarks>
    /// While you could use a data reader to create a single object in Oracle,
    /// more than likely you would use scalar types as a series of OUT or IN/OUT
    /// parameters.  This interface is more appropriate for SQL Server than it is
    /// for Oracle because SQL Server implicitly constructs a cursor while Oracle
    /// requires an explicit declaration of the cursor, whether generic or
    /// strongly typed.
    /// </remarks>
    /// <typeparam name="TDomainObject">type of domain object to create.</typeparam>
    public interface IDomainObjectFactory<TDomainObject>
    {
        /// <summary>
        /// Takes a DataReader and creates a domain object from it.
        /// </summary>
        /// <param name="reader">DataReader used to create the domain object.</param>
        /// <returns>Domain object instance.</returns>
        TDomainObject Construct(IDataReader reader);
    }

    /// <summary>
    /// This interface specifies the signature for a factory that
    /// creates a single simple domain object.
    /// </summary>
    /// <remarks>
    /// The domain object is simple because it does not contain 
    /// any collections of child objects.
    /// Use this interface when the Oracle stored procedure returns OUT or
    /// IN/OUT parameters that are scalar (i.e. no ref cursors).
    /// </remarks>
    /// <typeparam name="TDomainObject">Type of domain object to create.</typeparam>
    public interface ISimpleDomainObjectFactory<TDomainObject>
    {
        /// <summary>
        /// Takes an Enterprise Library Database object and a DbCommand to create a domain object.
        /// </summary>
        /// <param name="db">An Enterprise Library Database object.</param>
        /// <param name="command">A <see cref="DbCommand"/> object.</param>
        /// <returns>Domain object instance.</returns>
        TDomainObject Construct(Database db, DbCommand command);
    }

    /// <summary>
    /// This interface specifies the signature for a factory that
    /// creates a single complex domain object.
    /// </summary>
    /// <remarks>
    /// The domain object is complex because it contains one or more 
    /// collections of child objects.
    /// Use this interface when the Oracle stored procedure returns OUT or
    /// IN/OUT parameters, including ref cursors.
    /// </remarks>
    /// <typeparam name="TDomainObject">Type of domain object to create.</typeparam>
    public interface IComplexDomainObjectFactory<TDomainObject>
    {
        /// <summary>
        /// Takes an Enterprise Library Database object and a DbCommand to create a domain object.  
        /// Takes a DataReader to create children objects of the domain object.
        /// </summary>
        /// <param name="db">An Enterprise Library Database object.</param>
        /// <param name="command">A <see cref="DbCommand"/> object.</param>
        /// <param name="reader">DataReader used to create children object.</param>
        /// <returns>Domain object instance.</returns>
        TDomainObject Construct(Database db, DbCommand command, IDataReader reader);
    }

    /// <summary>
    /// This interface specifies the signature for a factory that
    /// creates multiple simple or complex domain objects.
    /// </summary>
    /// <remarks>
    /// The domain object is simple when it does not contain 
    /// any collections of child objects.  It is complex when it
    /// contains one or more collections of child objects.
    /// Use this interface when the Oracle stored procedure returns 
    /// one or more ref cursors.
    /// </remarks>
    /// <typeparam name="TDomainObject">Type of domain object to create.</typeparam>
    public interface IDomainObjectsFactory<TDomainObject>
    {
        /// <summary>
        /// Takes a DataReader and creates a set of domain objects from it.
        /// </summary>
        /// <param name="reader">DataReader used to create the domain objects.</param>
        /// <returns>Domain object instances contained in a generic List.</returns>
        List<TDomainObject> Construct(IDataReader reader);
    }
}
